<?php
/**
 * 案件文档控制器
 */

declare (strict_types = 1);

namespace app\controller\lawcase;

use app\BaseController;
use think\facade\Db;
use think\facade\Request;

class Casedoc extends BaseController
{
    /**
     * 格式化文件大小
     */
    private function formatFileSize($bytes)
    {
        if ($bytes == 0) return '0 B';
        $k = 1024;
        $sizes = ['B', 'KB', 'MB', 'GB'];
        $i = floor(log($bytes) / log($k));
        return round($bytes / pow($k, $i), 2) . ' ' . $sizes[$i];
    }

    /**
     * 获取文档列表
     */
    public function list()
    {
        try {
            $param = Request::param();
            $page = isset($param['page']) ? (int)$param['page'] : 1;
            $limit = isset($param['limit']) ? (int)$param['limit'] : 10;
            
            // 构建查询条件
            $where = [];
            $where[] = ['cd.delete_time', '=', 0];
            
            // 关键词搜索
            if (!empty($param['keywords'])) {
                $where[] = ['cd.title', 'like', '%' . trim($param['keywords']) . '%'];
            }
            
            // 按案件ID筛选
            if (!empty($param['case_id'])) {
                $where[] = ['cd.case_id', '=', $param['case_id']];
            }
            
            // 按案件编号筛选 - 新增功能
            if (!empty($param['case_code'])) {
                // 通过案件编号查询案件ID
                $caseId = Db::name('lawcase')
                    ->where('case_code', 'like', '%' . trim($param['case_code']) . '%')
                    ->value('id');
                
                if ($caseId) {
                    $where[] = ['cd.case_id', '=', $caseId];
                } else {
                    // 如果没有找到对应的案件，返回空结果
                    return json([
                        'code' => 0,
                        'msg' => 'success',
                        'data' => [],
                        'count' => 0,
                        'timestamp' => time()
                    ]);
                }
            }
            
            // 按文档类型筛选
            if (!empty($param['doc_type'])) {
                $where[] = ['cd.doc_type', '=', $param['doc_type']];
            }
            
            // 查询文档列表
            $list = Db::name('case_doc')
                ->alias('cd')
                ->join('lawcase l', 'cd.case_id = l.id', 'LEFT')
                ->join('admin a', 'cd.upload_uid = a.id', 'LEFT')
                ->field('cd.*, l.case_code, a.name as upload_user')
                ->where($where)
                ->page($page, $limit)
                ->order('cd.id', 'desc')
                ->select()
                ->each(function($item) {
                    $item['create_time'] = date('Y-m-d H:i', $item['create_time']);
                    $item['update_time'] = $item['update_time'] ? date('Y-m-d H:i', $item['update_time']) : '';
                    
                    // 文档类型名称，与Api.php中的get_doctype_list保持一致
                    $docTypeNames = [
                        1 => '起诉状',
                        2 => '答辩状',
                        3 => '代理词',
                        4 => '判决书',
                        5 => '裁定书',
                        6 => '调解书',
                        7 => '证据材料',
                        8 => '其他'
                    ];
                    $item['doc_type_name'] = isset($docTypeNames[$item['doc_type']]) ? $docTypeNames[$item['doc_type']] : '未知';
                    
                    // 获取文件信息（优化：统计文件数量，预加载小文件列表）
                    if (!empty($item['file_ids'])) {
                        // 统计文件数量（支持逗号分隔的多个文件ID）
                        $fileIdsArray = explode(',', $item['file_ids']);
                        $item['file_count'] = count($fileIdsArray);

                        // 如果文件数≤3，优先生成文件列表（减少前端请求）
                        if (count($fileIdsArray) <= 3) {
                            $fileList = Db::name('file')
                                ->where('id', 'in', $item['file_ids'])
                                ->select()
                                ->toArray();

                            // 处理文件列表，添加文件大小和扩展名
                            foreach ($fileList as &$file) {
                                $file['file_size'] = $file['filesize'] ?? 0;
                                $file['file_ext'] = pathinfo($file['name'], PATHINFO_EXTENSION);
                                $file['file_size_text'] = $this->formatFileSize($file['filesize'] ?? 0);
                            }
                            $item['file_list'] = $fileList;
                        } else {
                            // 文件较多时，不加载文件列表，节省性能
                            $item['file_list'] = [];
                        }

                        // 保留向后兼容的字段（只取第一个文件的信息）
                        $fileInfo = Db::name('file')
                            ->where('id', '=', $fileIdsArray[0])
                            ->find();

                        if ($fileInfo) {
                            $item['file_name'] = $fileInfo['name'];
                            $item['file_size'] = $fileInfo['filesize'];
                        } else {
                            $item['file_name'] = $item['title'];
                            $item['file_size'] = 0;
                        }
                    } else {
                        $item['file_name'] = $item['title'];
                        $item['file_size'] = 0;
                        $item['file_count'] = 0;
                        $item['file_list'] = [];
                    }
                    
                    return $item;
                });
            
            // 查询总数
            $count = Db::name('case_doc')
                ->alias('cd')
                ->join('lawcase l', 'cd.case_id = l.id', 'LEFT')
                ->where($where)
                ->count();
            
            return json([
                'code' => 0,
                'msg' => 'success',
                'data' => $list,
                'count' => $count,
                'timestamp' => time()
            ]);
        } catch (\Exception $e) {
            return json(['code' => 500, 'msg' => '获取失败: ' . $e->getMessage(), 'data' => null, 'timestamp' => time()]);
        }
    }
    
    /**
     * 查看文档详情
     */
    public function view()
    {
        $param = Request::param();
        
        if (empty($param['id'])) {
            return json(['code' => 400, 'msg' => '参数错误', 'data' => null, 'timestamp' => time()]);
        }
        
        try {
            $doc = Db::name('case_doc')
                ->alias('cd')
                ->join('lawcase l', 'cd.case_id = l.id', 'LEFT')
                ->join('admin a', 'cd.upload_uid = a.id', 'LEFT')
                ->field('cd.*, l.case_code, a.name as upload_user')
                ->where(['cd.id' => $param['id'], 'cd.delete_time' => 0])
                ->find();
            
            if (empty($doc)) {
                return json(['code' => 404, 'msg' => '文档不存在', 'data' => null, 'timestamp' => time()]);
            }
            
            // 格式化时间
            $doc['create_time'] = date('Y-m-d H:i', $doc['create_time']);
            $doc['update_time'] = $doc['update_time'] ? date('Y-m-d H:i', $doc['update_time']) : '';
            
            // 文档类型名称，与Api.php中的get_doctype_list保持一致
            $docTypeNames = [
                1 => '起诉状',
                2 => '答辩状',
                3 => '代理词',
                4 => '判决书',
                5 => '裁定书',
                6 => '调解书',
                7 => '证据材料',
                8 => '其他'
            ];
            $doc['doc_type_name'] = isset($docTypeNames[$doc['doc_type']]) ? $docTypeNames[$doc['doc_type']] : '未知';
            
            // 获取附件信息
            if (!empty($doc['file_ids'])) {
                $doc['file_array'] = Db::name('file')
                    ->where('id', 'in', $doc['file_ids'])
                    ->select()
                    ->toArray();
                
                // 为每个文件添加文件大小字段，确保字段名为file_size
                foreach ($doc['file_array'] as &$file) {
                    $file['file_size'] = $file['filesize'] ?? 0;
                    // 确保user_id字段存在
                    if (!isset($file['user_id'])) {
                        $file['user_id'] = 0;
                    }
                }
                
                // 添加文件原始名称和大小
                $fileInfo = Db::name('file')
                    ->where('id', '=', $doc['file_ids'])
                    ->find();
                
                if ($fileInfo) {
                    // 添加文件原始名称
                    $doc['file_name'] = $fileInfo['name'];
                    
                    // 使用数据库中存储的文件大小
                    $doc['file_size'] = $fileInfo['filesize'];
                } else {
                    $doc['file_name'] = $doc['title'];
                    $doc['file_size'] = 0;
                }
            } else {
                $doc['file_name'] = $doc['title'];
                $doc['file_size'] = 0;
            }
            
            return json([
                'code' => 0,
                'msg' => 'success',
                'data' => $doc,
                'timestamp' => time()
            ]);
        } catch (\Exception $e) {
            return json(['code' => 500, 'msg' => '获取失败: ' . $e->getMessage(), 'data' => null, 'timestamp' => time()]);
        }
    }
    
    /**
     * 新增文档
     */
    public function add()
    {
        $param = Request::param();
        $userId = $this->getUserId();
        
        // 数据验证
        if (empty($param['case_id'])) {
            return json(['code' => 400, 'msg' => '案件ID不能为空', 'data' => null, 'timestamp' => time()]);
        }
        
        if (empty($param['title'])) {
            return json(['code' => 400, 'msg' => '文档标题不能为空', 'data' => null, 'timestamp' => time()]);
        }
        
        if (empty($param['doc_type'])) {
            return json(['code' => 400, 'msg' => '文档类型不能为空', 'data' => null, 'timestamp' => time()]);
        }
        
        $data = [
            'case_id' => $param['case_id'],
            'title' => $param['title'],
            'doc_type' => $param['doc_type'],
            'file_ids' => $param['file_ids'] ?? '',
            'upload_uid' => $userId,
            'create_time' => time(),
            'update_time' => time()
        ];
        
        try {
            // 新增文档
            $docId = Db::name('case_doc')->insertGetId($data);
            
            return json(['code' => 0, 'msg' => '保存成功', 'data' => ['id' => $docId], 'timestamp' => time()]);
        } catch (\Exception $e) {
            return json(['code' => 500, 'msg' => '保存失败: ' . $e->getMessage(), 'data' => null, 'timestamp' => time()]);
        }
    }
    
    /**
     * 编辑文档
     */
    public function edit()
    {
        $param = Request::param();
        
        // 数据验证
        if (empty($param['id'])) {
            return json(['code' => 400, 'msg' => '参数错误', 'data' => null, 'timestamp' => time()]);
        }
        
        if (empty($param['title'])) {
            return json(['code' => 400, 'msg' => '文档标题不能为空', 'data' => null, 'timestamp' => time()]);
        }
        
        if (empty($param['doc_type'])) {
            return json(['code' => 400, 'msg' => '文档类型不能为空', 'data' => null, 'timestamp' => time()]);
        }
        
        // 检查文档是否存在
        $doc = Db::name('case_doc')
            ->where('id', $param['id'])
            ->where('delete_time', 0)
            ->find();
        
        if (!$doc) {
            return json(['code' => 404, 'msg' => '文档不存在', 'data' => null, 'timestamp' => time()]);
        }
        
        $data = [
            'id' => $param['id'],
            'title' => $param['title'],
            'doc_type' => $param['doc_type'],
            'file_ids' => $param['file_ids'] ?? $doc['file_ids'],
            'update_time' => time()
        ];
        
        try {
            // 更新文档
            Db::name('case_doc')->update($data);
            
            return json(['code' => 0, 'msg' => '更新成功', 'data' => ['id' => $param['id']], 'timestamp' => time()]);
        } catch (\Exception $e) {
            return json(['code' => 500, 'msg' => '更新失败: ' . $e->getMessage(), 'data' => null, 'timestamp' => time()]);
        }
    }
    
    /**
     * 删除文档（软删除）
     */
    public function delete()
    {
        $param = Request::param();
        
        // 获取ID - 支持多种参数格式
        $id = null;
        
        // 1. 从请求体data对象获取
        if (isset($param['data']['id'])) {
            $id = $param['data']['id'];
        }
        // 2. 从直接参数获取
        elseif (isset($param['id'])) {
            $id = $param['id'];
        }
        
        // 如果id是数组，取第一个值
        if (is_array($id)) {
            $id = $id[0];
        }
        
        if (empty($id)) {
            return json(['code' => 400, 'msg' => '参数错误', 'data' => null, 'timestamp' => time()]);
        }
        
        try {
            // 检查文档是否存在
            $doc = Db::name('case_doc')
                ->where('id', $id)
                ->where('delete_time', 0)
                ->find();
            
            if (!$doc) {
                return json(['code' => 404, 'msg' => '文档不存在', 'data' => null, 'timestamp' => time()]);
            }
            
            // 权限检查：只有超级管理员或文档创建人可以删除
            $userId = $this->getUserId();
            $userInfo = Db::name('admin')->where('id', $userId)->find();
            $isSuperAdmin = $userInfo && isset($userInfo['menus']) && strpos($userInfo['menus'], '*') !== false;
            
            if (!$isSuperAdmin && $doc['upload_uid'] != $userId) {
                return json(['code' => 403, 'msg' => '无权限删除此文档', 'data' => null, 'timestamp' => time()]);
            }
            
            // 软删除文档
            Db::name('case_doc')
                ->where('id', $id)
                ->update([
                    'delete_time' => time(),
                    'update_time' => time()
                ]);
            
            return json(['code' => 0, 'msg' => '删除成功', 'data' => null, 'timestamp' => time()]);
        } catch (\Exception $e) {
            return json(['code' => 500, 'msg' => '删除失败: ' . $e->getMessage(), 'data' => null, 'timestamp' => time()]);
        }
    }
    
    /**
     * 预览文档文件
     * 专门用于文件预览，通过Authorization头验证token
     */
    public function preview()
    {
        $param = Request::param();
        
        if (empty($param['file_id'])) {
            return json(['code' => 400, 'msg' => '文件ID不能为空', 'data' => null, 'timestamp' => time()]);
        }
        
        try {
            // 查询文件信息
            $fileInfo = Db::name('file')
                ->where('id', $param['file_id'])
                ->find();
            
            if (empty($fileInfo)) {
                return json(['code' => 404, 'msg' => '文件不存在', 'data' => null, 'timestamp' => time()]);
            }
            
            // 使用FileUploadConfig类获取文件路径，兼容新旧路径
            $filePath = \app\common\FileUploadConfig::getDownloadPath($fileInfo);
            
            if (!$filePath) {
                return json(['code' => 404, 'msg' => '文件不存在或已被删除', 'data' => null, 'timestamp' => time()]);
            }
            
            // 获取文件名
            $fileName = $fileInfo['name'];
            
            // 增加下载次数
            Db::name('file')
                ->where('id', $param['file_id'])
                ->inc('download', 1)
                ->update();
            
            // 设置响应头
            $mimeType = $this->getMimeType($filePath);
            
            // 处理中文文件名编码
            $encodedFileName = $fileName;
            if (preg_match('/[\x80-\xff]/', $fileName)) {
                // 包含中文，使用RFC 3986标准编码
                $encodedFileName = 'UTF-8\'\'' . rawurlencode($fileName);
            }
            
            // 设置Content-Disposition头为inline，表示在浏览器中直接显示
            $contentDisposition = 'inline; filename="' . $fileName . '"; filename*=UTF-8\'\'' . rawurlencode($fileName);
            
            // 创建响应对象
            $response = response(file_get_contents($filePath), 200, [
                'Content-Type' => $mimeType,
                'Content-Disposition' => $contentDisposition,
                'Content-Length' => filesize($filePath),
                'Cache-Control' => 'max-age=3600, must-revalidate',
                'Pragma' => 'public',
                'Access-Control-Allow-Origin' => '*',
                'Access-Control-Allow-Headers' => 'Content-Type, Content-Disposition, Authorization',
                'Access-Control-Expose-Headers' => 'Content-Disposition'
            ]);
            
            // 返回响应对象，确保中间件能处理
            return $response;
        } catch (\Exception $e) {
            return json(['code' => 500, 'msg' => '操作失败: ' . $e->getMessage(), 'data' => null, 'timestamp' => time()]);
        }
    }
    
    /**
     * 下载文档文件
     */
    public function download()
    {
        $param = Request::param();
        
        if (empty($param['file_id'])) {
            return json(['code' => 400, 'msg' => '文件ID不能为空', 'data' => null, 'timestamp' => time()]);
        }
        
        // 如果URL参数中有token，则验证token
        if (!empty($param['token'])) {
            try {
                $jwtKey = \think\facade\Config::get('jwt.key', 'default_secret_key');
                $token = str_replace('Bearer ', '', $param['token']);
                $decoded = \Firebase\JWT\JWT::decode($token, new \Firebase\JWT\Key($jwtKey, 'HS256'));
                // 设置用户ID到请求中，供后续权限检查使用
                Request::instance()->userId = $decoded->sub;
            } catch (\Exception $e) {
                return json(['code' => 401, 'msg' => '令牌无效或已过期', 'data' => null, 'timestamp' => time()]);
            }
        }
        
        try {
            // 查询文件信息
            $fileInfo = Db::name('file')
                ->where('id', $param['file_id'])
                ->find();
            
            if (empty($fileInfo)) {
                return json(['code' => 404, 'msg' => '文件不存在', 'data' => null, 'timestamp' => time()]);
            }
            
            // 使用FileUploadConfig类获取文件路径，兼容新旧路径
            $filePath = \app\common\FileUploadConfig::getDownloadPath($fileInfo);
            
            if (!$filePath) {
                return json(['code' => 404, 'msg' => '文件不存在或已被删除', 'data' => null, 'timestamp' => time()]);
            }
            
            // 获取文件名
            $fileName = $fileInfo['name'];
            
            // 增加下载次数
            Db::name('file')
                ->where('id', $param['file_id'])
                ->inc('download', 1)
                ->update();
            
            // 设置响应头
            $mimeType = $this->getMimeType($filePath);
            
            // 判断是否是预览请求
            $isPreview = isset($param['view']) && $param['view'] === 'true';
            
            // 处理中文文件名编码
            $encodedFileName = $fileName;
            if (preg_match('/[\x80-\xff]/', $fileName)) {
                // 包含中文，使用RFC 3986标准编码
                $encodedFileName = 'UTF-8\'\'' . rawurlencode($fileName);
            }
            
            // 设置Content-Disposition头
            $contentDisposition = $isPreview 
                ? 'inline; filename="' . $fileName . '"; filename*=UTF-8\'\'' . rawurlencode($fileName)
                : 'attachment; filename="' . $fileName . '"; filename*=UTF-8\'\'' . rawurlencode($fileName);
            
            // 创建响应对象
            $response = response(file_get_contents($filePath), 200, [
                'Content-Type' => $mimeType,
                'Content-Disposition' => $contentDisposition,
                'Content-Length' => filesize($filePath),
                'Cache-Control' => 'max-age=3600, must-revalidate',
                'Pragma' => 'public',
                'Access-Control-Allow-Origin' => '*',
                'Access-Control-Allow-Headers' => 'Content-Type, Content-Disposition',
                'Access-Control-Expose-Headers' => 'Content-Disposition'
            ]);
            
            // 返回响应对象，确保中间件能处理
            return $response;
        } catch (\Exception $e) {
            return json(['code' => 500, 'msg' => '操作失败: ' . $e->getMessage(), 'data' => null, 'timestamp' => time()]);
        }
    }
    
    /**
     * 获取文件的MIME类型
     */
    private function getMimeType($filePath)
    {
        // 简单的MIME类型映射
        $ext = strtolower(pathinfo($filePath, PATHINFO_EXTENSION));
        $mimes = [
            'txt' => 'text/plain',
            'pdf' => 'application/pdf',
            'doc' => 'application/msword',
            'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
            'xls' => 'application/vnd.ms-excel',
            'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
            'ppt' => 'application/vnd.ms-powerpoint',
            'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
            'jpg' => 'image/jpeg',
            'jpeg' => 'image/jpeg',
            'png' => 'image/png',
            'gif' => 'image/gif',
            'bmp' => 'image/bmp'
        ];
        
        return isset($mimes[$ext]) ? $mimes[$ext] : 'application/octet-stream';
    }
}